package com.nsl.my_youlai.bbu_return.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.nsl.my_youlai.bbu_return.convert.customized.SchemeExcelRecordCustomizedConverter;

import com.nsl.my_youlai.bbu_return.convert.mapstruct.SchemeExcelRecordMappingStructConverter;
import com.nsl.my_youlai.bbu_return.enums.check.CheckSchemeExcelRecordErrorType;
import com.nsl.my_youlai.mystar.easy_excel.check.NslUtilExcelValid;
import com.nsl.my_youlai.mystar.easy_excel.exception.ExcelNullValueException;
import com.nsl.my_youlai.bbu_return.model.bo.*;
import com.nsl.my_youlai.bbu_return.model.bo.check.CheckSchemeExcelRecord;
import com.nsl.my_youlai.bbu_return.model.bo.check.CheckSchemeExcelRecordMergeOneLine;
import com.nsl.my_youlai.mystar.easy_excel.model.ExcelReadCheck;
import com.nsl.my_youlai.bbu_return.model.vo.SchemeExcelRecordString;
import com.nsl.my_youlai.mystar.NslUtilFilePath;
import com.nsl.my_youlai.mystar.NslUtilList;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDateTime;
import java.util.*;

//todo:
//不为空检查，在listener中进行
//同一node id 在的bbu型号，经纬度等信息应该一致
@Slf4j
@Service
@RequiredArgsConstructor
public class LoadNodeBInfoByStringServiceImpl {

    private final SchemeExcelRecordMappingStructConverter schemeExcelRecordMappingStructConverter;


    /**
     * read scheme record 2 list
     * @param excelPath
     * @return
     */
    public void readBoardInfoSheet(String excelPath,List<SchemeExcelRecordString> schemeExcelRecordList,List<ExcelReadCheck> excelReadCheckList){
        EasyExcel.read(excelPath, SchemeExcelRecordString.class, new ReadListener<SchemeExcelRecordString>() {
            /**
             * 单次缓存的数据量
             */
            public static final int BATCH_COUNT = 100;
            /**
             *临时存储
             */
            private List<SchemeExcelRecordString> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
            @Override
            public void invoke(SchemeExcelRecordString data, AnalysisContext context) {
                data.setRowIndex(context.readRowHolder().getRowIndex());
                //log.info("data = {} ",data);
                cachedDataList.add(data);
                schemeExcelRecordList.add(data);

                try {
                    NslUtilExcelValid.valid(data);
                    excelReadCheckList.add(new ExcelReadCheck(context.readRowHolder().getRowIndex(),"必填项ok"));
                } catch (ExcelNullValueException e) {
                    throw new RuntimeException("必填字段未填写");
                }

                if (cachedDataList.size() >= BATCH_COUNT) {
                    saveData();
                    // 存储完成清理 list
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                saveData();
            }
            /**
             * 加上存储数据库
             */
            private void saveData() {

            }

            @Override
            public void onException(Exception exception, AnalysisContext context) {
                if (exception instanceof ExcelDataConvertException) {
                    ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
                    log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                            excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
                    //System.out.println(exception.getMessage());

                }

                //System.out.println(exception.getMessage());
                excelReadCheckList.add(new ExcelReadCheck(context.readRowHolder().getRowIndex(),exception.getMessage()));
            }

        }).sheet().doRead();

        log.info("schemeExcelRecordList.size = {} ",schemeExcelRecordList.size());

    }

    //板卡sheet中，回局机房不为空的记录，其nodebid 必须出现在传输表中的node id里面
    public void checkTransferNodeIdAndBoardIdOverlap(List<SchemeExcelRecordString> voStringList, List<CheckSchemeExcelRecord> checkSchemeExcelRecordList, Set<Integer> transferNodeIdSet){
        for (int i = 0; i < voStringList.size(); i++) {
            SchemeExcelRecordString schemeExcelRecordString=voStringList.get(i);
            String destinationPosition=schemeExcelRecordString.getDestinationPosition();
            if(destinationPosition!=null && !destinationPosition.trim().equals("")){
                String bbuNodeId=schemeExcelRecordString.getNodeBId();
                Integer bbuNodeIdInt=null;
                try{
                    bbuNodeIdInt=Integer.parseInt(bbuNodeId);
                }catch (Exception e){
                    continue;
                }
                if(!transferNodeIdSet.contains(bbuNodeIdInt)){
                    CheckSchemeExcelRecord checkSchemeExcelRecord=new CheckSchemeExcelRecord();
                    checkSchemeExcelRecord.setRowIndex(schemeExcelRecordString.getRowIndex());
                    checkSchemeExcelRecord.setType("错误");
                    checkSchemeExcelRecord.setTitle("本列nodeb_id 在传输需求表 中不存在");
                    checkSchemeExcelRecord.setExcelInputString(bbuNodeId);
                    checkSchemeExcelRecord.setCheckSchemeExcelRecordErrorType(CheckSchemeExcelRecordErrorType.BBU_SHEET_TRANSFER_SHEET_NODE_ID_OVERLAP);
                    checkSchemeExcelRecordList.add(checkSchemeExcelRecord);

                }

            }

        }

    }

    public List<SchemeExcelRecordBo> toBoList(List<SchemeExcelRecordString> voStringList,List<CheckSchemeExcelRecord> checkSchemeExcelRecordList){
        List<SchemeExcelRecordBo> boList=null;
        if (voStringList != null) {
            boList=schemeExcelRecordMappingStructConverter.toBoList(voStringList);
            SchemeExcelRecordCustomizedConverter.toBoList(voStringList,boList,checkSchemeExcelRecordList);
        }
        return boList;
    }

    //将转换成bo阶段的错误输出
    public void writeCheckResultOfToBoList(String excelPath,String outputDir,int resultSize,List<CheckSchemeExcelRecord> checkSchemeExcelRecordList){
        List<CheckSchemeExcelRecordMergeOneLine> outList=new ArrayList<>(resultSize);
        for (int i = 0; i < resultSize; i++) {
            CheckSchemeExcelRecordMergeOneLine line = new CheckSchemeExcelRecordMergeOneLine();
            outList.add(line);
            line.setRowIndex(i + 1);

            for (CheckSchemeExcelRecord checkSchemeExcelRecord : checkSchemeExcelRecordList) {
                if (checkSchemeExcelRecord.getRowIndex().intValue() == line.getRowIndex()) {
                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.ACTION_ERROR)) {
                        line.setActionError(CheckSchemeExcelRecordErrorType.ACTION_ERROR.getLabel());
                    }

//                    if(checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.GENERATION_TYPE_ERROR)){
//                        line.setGenerationTypeError(CheckSchemeExcelRecordErrorType.GENERATION_TYPE_ERROR.getLabel());
//                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.BOARD_TYPE_ERROR)) {
                        line.setBoardTypeError(CheckSchemeExcelRecordErrorType.BOARD_TYPE_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.NODE_iD_ERROR)) {
                        line.setNodeIdError(CheckSchemeExcelRecordErrorType.NODE_iD_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.BBU_MODEL_ERROR)) {
                        line.setBbuModelError(CheckSchemeExcelRecordErrorType.BBU_MODEL_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.VENDOR_ERROR)) {
                        line.setVendorError(CheckSchemeExcelRecordErrorType.VENDOR_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.REQUIRED_SLOT_INDEX_ERROR)) {
                        line.setRequiredSlotIndexError(CheckSchemeExcelRecordErrorType.REQUIRED_SLOT_INDEX_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.REQUIRED_COLUMNS_NULL_ERROR)) {
                        line.setRequiredColumnsNullError(checkSchemeExcelRecord.getTitle());

                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.REQUIRED_DESTINATION_ID_AND_SLOT_INDEX_ERROR)) {
                        line.setRequiredDestinationIdAndSlotIndexError(CheckSchemeExcelRecordErrorType.REQUIRED_DESTINATION_ID_AND_SLOT_INDEX_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.BBU_VERDOR_MATCH)) {
                        line.setBbuVendorMatchError(CheckSchemeExcelRecordErrorType.BBU_VERDOR_MATCH.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.VENDOR_SWITCH_BOARD_ERROR)) {
                        line.setVendorSwitchMatchError(CheckSchemeExcelRecordErrorType.VENDOR_SWITCH_BOARD_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.TAC_NOT_NUMBER_ERROR)) {
                        line.setSourceBbuTacNotNumber(CheckSchemeExcelRecordErrorType.TAC_NOT_NUMBER_ERROR.getLabel());
                    }

                    //地市错误
                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.CITY_ERROR)) {
                        line.setCityError(CheckSchemeExcelRecordErrorType.CITY_ERROR.getLabel());
                    }
                    //机房类型
                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.MACHINE_ROOM_CATEGORY_ERROR)) {
                        line.setRoomCategory(CheckSchemeExcelRecordErrorType.MACHINE_ROOM_CATEGORY_ERROR.getLabel());
                    }
                    //机房归属
                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.MACHINE_ROOM_OWNERSHIP_ERROR)) {
                        line.setRoomOwnership(CheckSchemeExcelRecordErrorType.MACHINE_ROOM_OWNERSHIP_ERROR.getLabel());
                    }
                    //宏站or室分
                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.INDOOR_OUTDOOR_ERROR)) {
                        line.setIndoorOutdoor(CheckSchemeExcelRecordErrorType.INDOOR_OUTDOOR_ERROR.getLabel());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.DISMANTLE_SETUP_ACTION_NEW_BBU_ID_AND_SLOT_BLANK_ERROR)) {
                        line.setDismantleSetupActionNewBbuIdAndSlotNotBlankError(checkSchemeExcelRecord.getTitle());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.BBU_ID_UNKNOWN)) {
                        line.setSourceBbuIdUnknown(checkSchemeExcelRecord.getTitle());
                    }

                    if (checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.TAC_UNKNOWN)) {
                        line.setSourceTacUnknown(checkSchemeExcelRecord.getTitle());
                    }
                    if(checkSchemeExcelRecord.getCheckSchemeExcelRecordErrorType().equals(CheckSchemeExcelRecordErrorType.BBU_SHEET_TRANSFER_SHEET_NODE_ID_OVERLAP)){
                        line.setNodeIdOverlapOfBoardAndTransferSheet(checkSchemeExcelRecord.getTitle());
                    }
                }
            }
            //总校验
            List<String> sumResult = new ArrayList<>();
            sumResult.add(line.getNodeIdError());//1
            sumResult.add(line.getActionError());//2
            sumResult.add(line.getRequiredDestinationIdAndSlotIndexError());//3
            sumResult.add(line.getVendorError());//4
            sumResult.add(line.getRequiredSlotIndexError());//5
            sumResult.add(line.getBbuModelError());//6
            sumResult.add(line.getBbuVendorMatchError());//7
            sumResult.add(line.getBoardTypeError());//8
            sumResult.add(line.getSourceBbuTacNotNumber());//9
            sumResult.add(line.getRequiredColumnsNullError());//10
            sumResult.add(line.getVendorSwitchMatchError());//11
            sumResult.add(line.getCityError());//12
            sumResult.add(line.getIndoorOutdoor());//13
            sumResult.add(line.getRoomCategory());//14
            sumResult.add(line.getRoomOwnership());//15
            sumResult.add(line.getDismantleSetupActionNewBbuIdAndSlotNotBlankError());//16
            sumResult.add(line.getSourceBbuIdUnknown());//17
            sumResult.add(line.getSourceTacUnknown());//18
            sumResult.add(line.getNodeIdOverlapOfBoardAndTransferSheet());//19


            //_s: skip
            if (line.getRequiredColumnsNullError().contains("整合方式")) {
                line.setSummary("整合方式未明确");
            }else if(stringListContainsStringFragment(sumResult,"_s")){
                line.setSummary("忽略");
            }  else if ((NslUtilList.repeatTimesOfObject(sumResult, "ok") != 18)) {
                line.setSummary("有误");;
            } else if (stringListContainsStringFragment(sumResult, "_a")) {
                line.setSummary("注意");
            }

            //(NslUtilList.repeatTimesOfObject(sumResult, "ok") != 17
            // line.setSummary("有误");
        }

        String resultPath=outputDir+File.separator+NslUtilFilePath.getFileNameWithoutExtension(excelPath)+"_数据有效性检查"+LocalDateTime.now().getSecond()+ LocalDateTime.now().getHour() +"."+NslUtilFilePath.getFileExtension(excelPath);
        EasyExcel.write(resultPath, CheckSchemeExcelRecordMergeOneLine.class).sheet("有效性检查").doWrite(outList);
    }

    private boolean stringListContainsStringFragment(List<String> list,String stringFragment) {
        for (String o : list) {
            if(o.contains(stringFragment)){
                return true;
            }
        }
        return false;
    }

    //检查 bbu回局机房名称不为空的nodeb id 在传输表中出现



    public Map<Integer,BBUFrame>  buildBBUFrameList(List<SchemeExcelRecordBo> schemeExcelRecordList, List<CheckSchemeExcelRecord> checkSchemeExcelRecordList){
        Map<Integer,BBUFrame> bbuFrameMap=new HashMap<>();
        for (int i = 0; i < schemeExcelRecordList.size(); i++) {

            SchemeExcelRecordBo schemeExcelRecord=schemeExcelRecordList.get(i);
            Integer nodeBId=schemeExcelRecord.getNodeId();
            BBUFrame bbuFrame=null;
            if(!bbuFrameMap.keySet().contains(nodeBId)){
                bbuFrame=new BBUFrame();

                // nodeB_Id 转换成数值
                bbuFrame.setNodeBId(schemeExcelRecord.getNodeId());
                // 厂家，4/5G网络类型 转换成枚举，规范输入
                bbuFrame.setVendor(schemeExcelRecord.getVendor());
                bbuFrame.setGenerationType(schemeExcelRecord.getGenerationType());
                bbuFrame.setVendorBbuModelEnum(schemeExcelRecord.getVendorBbuModelEnum());

                bbuFrame.setModel(schemeExcelRecord.getBbuModel());
                bbuFrame.setTac(schemeExcelRecord.getSourceTac());
                bbuFrameMap.put(nodeBId,bbuFrame);
            }else{
                bbuFrame=bbuFrameMap.get(nodeBId);
            }
//            if(schemeExcelRecord.getBoardType().equals(BoardTypeEnum.FRAME_AND_FUN_BOARD)){
//                bbuFrame.setBbuFrameAndFunCounter(bbuFrame.getBbuFrameAndFunCounter()+1);
//            }else{
//                buildBbuSlot(bbuFrame,schemeExcelRecord);
//            }
            buildBbuSlot(bbuFrame,schemeExcelRecord);
        }
        return bbuFrameMap;
    }

    private void buildBbuSlot(BBUFrame bbuFrame, SchemeExcelRecordBo schemeExcelRecord) {
      Map<Integer, BBUSlot> bbuSlotMap=bbuFrame.getBbuSlotMap();
      BBUSlot bbuSlot=null;
      //槽道 -1 表示是机框和风扇,特殊处理

        Integer slotIndex=schemeExcelRecord.getSlotIndex();

        if(bbuSlotMap.containsKey(slotIndex)){
              bbuSlot=bbuSlotMap.get(slotIndex);
        }else{
            bbuSlot=new BBUSlot();
        }

        bbuSlot.setSlotIndex(slotIndex);
        BbuBoard bbuBoard=new BbuBoard();
        bbuBoard.setBoardType(schemeExcelRecord.getBoardType());
        bbuBoard.setVendor(schemeExcelRecord.getVendor());
        bbuBoard.setGenerationType(schemeExcelRecord.getGenerationType());
        bbuBoard.setModel(schemeExcelRecord.getBoardModel());
        bbuBoard.setActionEnum(schemeExcelRecord.getAction());
        bbuBoard.setDestinationNodeBId(schemeExcelRecord.getDestinationNodeBId());
        bbuBoard.setDestinationSlotIndex(schemeExcelRecord.getDestinationSlotIndex());
        bbuBoard.setTac(bbuFrame.getTac());

        bbuSlot.getBbuBoardList().add(bbuBoard);
        bbuSlotMap.put(slotIndex,bbuSlot);
    }


    //读excel，并检查 必填项
    public void readBoardInfoSheetAndCheckNotNull(String excelPath,List<SchemeExcelRecordString> schemeExcelRecordList,List<ExcelReadCheck> excelReadCheckList,String outputDir){
        readBoardInfoSheet(excelPath,schemeExcelRecordList,excelReadCheckList);
        String checkReadExcelResultPath=outputDir+File.separator+NslUtilFilePath.getFileNameWithoutExtension(excelPath)+"_必填项检查."+NslUtilFilePath.getFileExtension(excelPath);
       // System.out.println(checkReadExcelResultPath);
        EasyExcel.write(checkReadExcelResultPath, ExcelReadCheck.class).sheet("模板").doWrite(excelReadCheckList);
    }
}
